import types
import typing
from copy import copy
from functools import reduce
from typing import Any, List, Optional, Sequence, Tuple as TypedTuple, Type, Union, Set

from pypika.terms import Function, EmptyCriterion, Term, Field
from pypika.utils import builder
from pypika.queries import QueryBuilder, Schema, Table
from frappe.query_builder.terms import ParameterizedValueWrapper
from frappe.utils import get_table_name
from frappe.query_builder.utils import PseudoColumnMapper
from frappe.query_builder.builder import Base
from .dm_dialects import DmQuery, DmQueryBuilder

class Dm(Base, DmQuery):
    """达梦数据库查询构建器"""
    field_translation = types.MappingProxyType({ 
        "table_rows": "num_rows",
        "character_maximum_length": "data_length",  
        "is_nullable": "nullable"           
    })
    schema_translation = types.MappingProxyType({
        "tables": "all_tables",
        "columns": "ALL_COLUMNS"        
    })

    _BuilderClasss = DmQueryBuilder

    @classmethod
    def _builder(cls, *args, **kwargs) -> "DmQueryBuilder":
        return super()._builder(*args, wrapper_cls=ParameterizedValueWrapper, **kwargs)

    @classmethod
    def Field(cls, field_name, *args, **kwargs):
        if field_name in cls.field_translation:
            field_name = cls.field_translation[field_name]
        return Field(field_name, *args, **kwargs)

    @classmethod
    def from_(cls, table, *args, **kwargs):
        if isinstance(table, Table):
            if table._schema:
                if table._schema._name == "information_schema":
                    table = cls.schema_translation.get(table._table_name) or table
        elif isinstance(table, str):
            table = cls.DocType(table)
        return super().from_(table, *args, **kwargs)

    @builder
    def where(self, criterion: Union[Term, EmptyCriterion]) -> "QueryBuilder":
        if isinstance(criterion, EmptyCriterion):
            return

        if not self._validate_table(criterion):
            self._foreign_table = True

        if self._wheres:
            self._wheres &= criterion
        else:
            self._wheres = criterion 